﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Genuilder.Extensibility
{
	public class ExtensionContext
	{
		IGenLogger _GlobalLogger;
		public ExtensionContext(IExtension extension, ExecutionContext executionContext, IGenLogger logger)
		{
			this._Extension = extension;
			_GlobalLogger = logger;
			_Logger = logger.CreateExtensionLogger(_Extension);
			this._ExecutionContext = executionContext;
		}

		[Obsolete("Use ExtensionContext.GenItems.CreateNew(string childName) instead")]
		public GenItem CreateChildItem(string childName)
		{
			return GenItems.CreateNew(childName);
		}

		public GenItemRepository GenItems
		{
			get
			{
				return _ExecutionContext.GenItems;
			}
		}

		private readonly ExecutionContext _ExecutionContext;
		public ExecutionContext ExecutionContext
		{
			get
			{
				return _ExecutionContext;
			}
		}
		private readonly IExtension _Extension;
		public IExtension Extension
		{
			get
			{
				return _Extension;
			}
		}

		private readonly IExtensionLogger _Logger;
		public IExtensionLogger Logger
		{
			get
			{
				return _Logger;
			}
		}

	}


	public class ExecutionContext
	{


		internal GenItemRepository _SourceFileRepository;

		public IEnumerable<SourceFile> SourceFiles
		{
			get
			{
				return _SourceFileRepository.Select(s => s.SourceFile);
			}
		}

		readonly IGenLogger _Logger;
		public ExecutionContext(List<SourceFile> sourceFiles, GenEngineStartInfo startInfo, IGenLogger logger)
		{
			if(logger == null)
				throw new ArgumentNullException("logger");
			_StartInfo = startInfo;
			_Logger = logger;
			_SourceFileRepository = new GenItemRepository(this);
			_SourceFileRepository.RegisterAll(sourceFiles.Select(s => this.Create(s, false)));
			if(startInfo.RunHistory != null)
			{
				foreach(var item in startInfo.RunHistory.GenItems.Where(i => i.Generated))
				{
					var sourceItem = item.ToSourceFile(this);
					if(item.Parent == null)
						_SourceFileRepository.Register(sourceItem);
					else
					{
						var parentFile = _SourceFileRepository.Resolve(new SourceFile(item.Parent, (SourceType)Enum.Parse(typeof(SourceType), item.ParentType)));
						if(parentFile != null)
							parentFile.Children.Add(sourceItem);
					}
				}
			}
		}

		private readonly GenEngineStartInfo _StartInfo;
		public GenEngineStartInfo StartInfo
		{
			get
			{
				return _StartInfo;
			}
		}

		internal ExtensionContext CreateExtensionContext(IExtension extension)
		{
			return new ExtensionContext(extension, this, _Logger);
		}

		internal RunHistory CreateHistory()
		{
			return new RunHistory()
			{
				GenItems = _SourceFileRepository.Select(i => GenItemHistory.CreateFrom(i)).ToList()
			};
		}

		public GenItemRepository GenItems
		{
			get
			{
				return _SourceFileRepository;
			}
		}


		internal GenItem Create(SourceFile sourceFile, bool generated)
		{
			return new GenItem(sourceFile, StartInfo, _Logger, generated);
		}


	}
}
